package com.enfi.api.configuration;

import com.enfi.api.filter.ImAuthenticationFilter;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * @author wind
 * @since  2020/4/3
 */
@Configuration
public class MultiHttpSecurityConfig {

    @Configuration
    @Order(200)
    public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

        @Resource
        private SysConfig sysConfig;
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().regexMatchers("(\\S)*(\\S\\.[\\w]{0,8})(.*)");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            ImAuthenticationFilter imAuthenticationFilter=new ImAuthenticationFilter(sysConfig.getSecurity().getCheckSession(),sysConfig.getIgnoreUrls());
            String[] a=sysConfig.getIgnoreUrls()==null?new String[]{}:sysConfig.getIgnoreUrls().stream().toArray(String[]::new);
            http.addFilterBefore(imAuthenticationFilter, RememberMeAuthenticationFilter.class).formLogin() // 表单方式
                    .and()
                    .authorizeRequests()
                    .antMatchers(a).permitAll()
                    .anyRequest()  // 所有请求
                    .authenticated()
                    .and()
                    .csrf().disable()
                    .headers().frameOptions().disable()
                    .and().cors();
        }
    }

    @Configuration
    @Order(2)
    public  static class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
        private final String adminContextPath;

        public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
            this.adminContextPath = adminServerProperties.getContextPath();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
            successHandler.setTargetUrlParameter("redirectTo");
            successHandler.setDefaultTargetUrl(adminContextPath + "/");
            http.antMatcher(adminContextPath + "/**").authorizeRequests()
                    .antMatchers(adminContextPath + "/assets/**").permitAll()
                    .antMatchers(adminContextPath + "/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
                    .logout().logoutUrl(adminContextPath + "/logout").and()
                    .httpBasic().and()
                    .csrf()
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                    .ignoringAntMatchers(
                            adminContextPath + "/instances",
                            adminContextPath + "/actuator/**"
                    );
            // @formatter:on
        }
    }

    @Configuration
    @Order(1)
    public static class ActuatorWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Value("${spring.security.user.roles}")
        private String role;
        @Override
        protected void configure(HttpSecurity http) throws Exception {
             String basePath="/actuator";
            http.antMatcher(basePath+"/**").authorizeRequests()
                    //拦截所有endpoint，拥有ACTUATOR_ADMIN角色可访问，否则需登录
                    .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR_ADMIN")
                    //静态文件允许访问
                    .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                    //根路径允许访问
                    .antMatchers(basePath+"/").permitAll()
                    //所有请求路径可以访问
                    .antMatchers(basePath+"/**").permitAll()
                    .and().httpBasic()
                    .and().csrf().disable();

        }
    }
}
